package internal

import (
	"github.com/BurntSushi/toml"
	"lol.com/feb214-game/nest.git/leaf"
	"lol.com/feb214-game/nest.git/log"
	"lol.com/feb214-game/nest.git/tools/fs"
	"talent.com/cube/conf/g"
)

type serverConf struct {
	EnabledGame []string
	WSAddr      string
	ApiAddr     string
	AdminAddr   string
	URL         string
	ProfilePort int
	HotReload   bool
	PullConfUrl string
}

type commonGameConf struct {
	CloseTableWhenIdle bool
	IndexBetLimit      int64
	AutoRestore        bool
	TestMode           bool
	PoolRefreshOffset  int64
}

type dbConf struct {
	Host    string
	IsDebug bool `toml:"Debug"`
}

type redisConf struct {
	Host     string
	Password string
	Index    int
}

type logConf struct {
	Path  string
	Level string
}

type mongoConf struct {
	Host string
}

type gConfConf struct {
	ServerHost  string
	AppKey      string
	AppSecret   string
	ConfDataDir string
	Cluster     string
}

type kafkaConf struct {
	Host []string
}

type apolloConf struct {
	Host  string
	AppId string
}

type ServerConfig struct {
	Server  *serverConf
	Game    *commonGameConf
	DB      *dbConf
	Mongo   *mongoConf
	Log     *logConf
	Redis   *redisConf
	IMRedis *redisConf
	GConf   *gConfConf
	Kafka   *kafkaConf
	Apollo  *apolloConf
}

func (sc *ServerConfig) IsEnabled(gameType int32) bool {
	label := g.GetCodeLabel(gameType)
	for _, game := range sc.Server.EnabledGame {
		if game == label {
			return true
		}
	}
	return false
}

type ServerConfigParser struct {
	fs.ParserMixIn
	config *ServerConfig
	Init   bool
}

func (scp *ServerConfigParser) ReloadConfig(path string, init bool) bool {
	var sc ServerConfig
	modified, lastTs := scp.CheckModify(path)
	if !modified {
		return false
	}
	if _, err := toml.DecodeFile(path, &sc); err != nil {
		if init {
			panic(err)
		} else {
			log.Error("can't decode %v", path)
			return false
		}
	}
	scp.Lock()
	if init {
		log.InitLogger(sc.Log.Level, sc.Log.Path)
		leaf.EnableProfile(sc.Server.ProfilePort)
		if sc.Log.Level == "debug" {
			leaf.ConfigLog(true)
		} else {
			leaf.ConfigLog(false)
		}
		scp.config = &sc
	} else {
		//仅允许部分热加载
		scp.config.Log.Level = sc.Log.Level
		scp.config.Game = sc.Game
		log.ReloadLogger(sc.Log.Level)
	}
	scp.SetLastModifyTime(path, lastTs)
	scp.Unlock()
	return true
}

func (scp *ServerConfigParser) ReloadCallback(value string) error {
	var sc ServerConfig

	if _, err := toml.Decode(value, &sc); err != nil {
		if scp.Init {
			panic(err)
		} else {
			log.Error("can't decode %v", value)
			return err
		}
	}
	scp.Lock()
	if scp.Init {
		log.InitLogger(sc.Log.Level, sc.Log.Path)
		leaf.EnableProfile(sc.Server.ProfilePort)
		if sc.Log.Level == "debug" {
			leaf.ConfigLog(true)
		} else {
			leaf.ConfigLog(false)
		}
		scp.config = &sc
	} else {
		//仅允许部分热加载
		scp.config.Log.Level = sc.Log.Level
		scp.config.Game = sc.Game
		log.ReloadLogger(sc.Log.Level)
	}
	scp.Init = false
	scp.Unlock()
	return nil
}

func (scp *ServerConfigParser) GetConfig() interface{} {
	scp.RLock()
	defer scp.RUnlock()
	return scp.config
}
